﻿using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;

namespace Negocio
{
   public class PlayerExecution: PersistentObject
    {
        private string evaluationName;
        private DateTime date;
        private Player player;
        private ObservableCollection<TestValue> values;
        private string groupName;
        private string comments;
        

        public PlayerExecution()
        {
            this.EvaluationName = "";
            this.Date = new DateTime();
            this.Player = new Player();
            this.Values = new ObservableCollection<TestValue>();
            this.groupName = "";
            comments = "";
        }

        public string EvaluationName 
        {
            get { return this.evaluationName;}
            set { this.evaluationName = value;}
        }

        public DateTime Date 
        {
            get { return this.date;}
            set { this.date = value;}
        }

        public Player Player
        {
            get { return this.player;}
            set { this.player = value;}
        }

        public ObservableCollection<TestValue> Values 
        {
            get { return this.values; }
            set { this.values = value; }
        }

        public string GroupName 
        {
            get { return this.groupName; }
            set { this.groupName = value; }
        }

        public string Comments 
        {            
            get { return this.comments;}
            set { this.comments = value;}
        }
               
        public bool addValue(TestValue oneValue)
        {
            bool ret = false;
            if (!this.Values.Contains(oneValue))
            {
                this.values.Add(oneValue);
                ret = true;
            }            
            return ret;
        }

        public void removeValue(TestValue oneValue)
        {
            this.Values.Remove(oneValue);
        }
        

       //falta Pi y potencia y raiz
        public float calculateValue(int pos, string sequence)
        {            
            float ret = 0;
            float firstNumber = 0;
            float secondNumber = 0;
            char actualOperator = ' ';
            int i = 0;
            bool comienzo = false;
            if (sequence.Equals("n/a"))
            {
                ret = this.Values[pos].ValueExecution;
            }
            else 
            {
                while(i < sequence.Length)
                {
                    switch (sequence[i])
                    { 
                        case '(':
                            //algoritmo para parentesis
                            string subSequence = "";
                            int parQuantity = 1;                            
                            if (i != 0) 
                            {
                                if (sequence[i - 1] != '+' && sequence[i-1] != '-' && sequence[i-1] != '*' && sequence[i-1] != '/' && sequence[i-1] != '$' && sequence[i-1] != '^')
                                {
                                    actualOperator = '*';
                                }
                            }
                            i = i + 1;
                            //armo cuenta dentro del parentesis
                            bool salir = false;
                            //while (sequence[i] != ')' || parQuantity > 0)
                            while(!salir)
                            {
                                if (sequence[i] == ')')
                                {
                                    parQuantity = parQuantity - 1;
                                    if (parQuantity > 0)
                                    {
                                        subSequence = subSequence + sequence[i];
                                    }
                                    else 
                                    {
                                        salir = true;
                                    }
                                    //i = i + 1;
                                }
                                else
                                {
                                    if (sequence[i] == '(')
                                    {
                                        parQuantity = parQuantity + 1;
                                    }
                                    subSequence = subSequence + sequence[i];
                                }
                                i = i + 1;
                            }
                            //llamada recursiva
                            if (firstNumber != 0 || comienzo)
                            {
                                secondNumber = calculateValue(pos, subSequence);
                            }
                            else 
                            {
                                firstNumber = calculateValue(pos, subSequence);
                            }
                            //i = i + 1;
                            break;
                        case '[':
                            //logica para cuando toma valores de otros test
                            i = i + 1;
                            string aux = "";
                            while (sequence[i] != ']')
                            {
                                aux = aux + sequence[i];
                                i = i + 1;
                            }
                            string testName = aux;
                            int testIndex = 0;
                            for (int j = 0; j < this.Values.Count; j++)
                            {
                                if (testName.Equals(this.values[j].Test.Name))
                                {
                                    testIndex = j;
                                    j = this.Values.Count;
                                }
                            }
                            i = i + 1;                            
                            if (firstNumber != 0 || comienzo)
                            {
                                secondNumber = calculateValue(testIndex, this.Values[testIndex].Test.Sequence);
                            }
                            else
                            {
                                firstNumber = calculateValue(testIndex, this.Values[testIndex].Test.Sequence);
                                comienzo = true;
                            }
                            break;
                        case '+':
                            actualOperator = '+';
                            i = i + 1;
                            break;
                        case '-':
                            actualOperator = '-';
                            i = i + 1;
                            break;
                        case '*':
                            actualOperator = '*';
                            i = i + 1;
                            break;
                        case '/':
                            actualOperator = '/';
                            i = i + 1;
                            break;
                        case '$':
                            actualOperator = '$';
                            i = i + 1;
                            break;
                        case '^':
                            actualOperator = '^';
                            i = i + 1;
                            break;
                        case '?':
                            if (firstNumber != 0 || comienzo)
                            {
                                secondNumber = float.Parse(Math.PI.ToString()); 
                            }
                            else
                            {
                                firstNumber = float.Parse(Math.PI.ToString());
                            }
                            i = i + 1;
                            break;
                        default:
                            string actualNumber = "";
                            //armo el nro con todas las cifras
                            while (i < sequence.Length && sequence[i] != '+' && sequence[i] != '-' && sequence[i] != '*' && sequence[i] != '/' && sequence[i] != '$' && sequence[i] != '^' && sequence[i] != ')')
                            {
                                actualNumber = actualNumber + sequence[i];
                                i = i + 1;
                            }
                            if (firstNumber != 0 || comienzo)
                            {
                                secondNumber = float.Parse(actualNumber);
                            }
                            else
                            {
                                firstNumber = float.Parse(actualNumber);
                                comienzo = true;
                            }
                            break;
                    }                     
                    if ((comienzo || firstNumber != 0) && actualOperator != ' ' && secondNumber != 0)
                    {
                        switch (actualOperator)
                        { 
                            case '+':
                                ret = firstNumber + secondNumber;
                                break;
                            case '-':
                                ret = firstNumber - secondNumber;
                                break;
                            case '*':
                                ret = firstNumber * secondNumber;
                                break;
                            case '/':
                                ret = firstNumber / secondNumber;
                                break;
                            case '$':
                                secondNumber = 1/secondNumber;
                                ret = float.Parse(Math.Pow(double.Parse(firstNumber.ToString()), double.Parse(secondNumber.ToString())).ToString());
                                break;
                            case '^':
                                ret = float.Parse(Math.Pow(double.Parse(firstNumber.ToString()), double.Parse(secondNumber.ToString())).ToString());                                
                                break;
                        }
                        firstNumber = ret;
                        secondNumber = 0;
                        actualOperator = ' ';
                    }                    
                }
            }
            return ret;
        }
        
        public override bool Equals(object obj)
        {
            PlayerExecution ejec = (PlayerExecution)obj;
            return ((this.EvaluationName.Equals(ejec.EvaluationName)) && (this.Date.Equals(ejec.Date)) && (this.Player.Equals(ejec.Player)) && this.GroupName.Equals(ejec.GroupName));
        }        
        
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        
    }
}
